//
// Created by wxd on 2025/8/5.
//

#pragma once

#ifndef ENGINE_BASEGEOMETRY_H
#define ENGINE_BASEGEOMETRY_H

#include <glad/glad.h>
#include "IGeometry.h"
#include <vector>
#include <unordered_map>
#include <memory>
#include "../glFramework/bo/EBO.h"
#include "../glFramework/bo/VAO.h"
#include "../glFramework/bo/VBO.h"
#include "glm/glm.hpp"
#include "glm/gtc/constants.hpp"
#include "../global/generator_id.h"
#include "../utils/RenderEngineLogger.h"

using VBOType = IGeometry::VBOType;

enum class DrawType {
    NONE,
    DRAW_ELEMENTS,
    DRAW_ARRAYS
};

enum class GeometryType {
    NONE,

    TRIANGLE, PLANE, CIRCLE, POLYGON,

    CUBE, CUBOID, SPHERE,
};

struct VBOStruct {
    VBO* vbo { nullptr };
    VBOType type = VBOType::NONE;

    VBOStruct() = default;
};

// 定义OpenGL坐标系的默认的标准基向量 (+-x, +-y, +-z)
struct OrthoBase {
    glm::vec3 ex = glm::vec3(1.f, 0.f, 0.f);
    glm::vec3 ey = glm::vec3(0.f, 1.f, 0.f);
    glm::vec3 ez = glm::vec3(0.f, 0.f, 1.f);
    glm::vec3 nex = -ex;
    glm::vec3 ney = -ey;
    glm::vec3 nez = -ez;

    OrthoBase() {}
    OrthoBase(const glm::vec3& ex, const glm::vec3& ey, const glm::vec3& ez,
              const glm::vec3& nex, const glm::vec3& ney, const glm::vec3& nez)
              : ex(ex), ey(ey), ez(ez), nex(nex), ney(ney), nez(nez) {}
};

class BaseGeometry : public IGeometry {
public:
    BaseGeometry() {
        m_GeoTraceId = IDGenerator::getInstance().generateString(IDPrefix::GEOMETRY);
        Log.msg("BaseGeometry").param("GeoTraceId", m_GeoTraceId).d();
    }
    BaseGeometry(DrawType drawType, GLenum drawMode, GeometryType geometryType)
    : m_DrawType(drawType), m_DrawMode(drawMode), m_GeometryType(geometryType) {}

    // 克隆接口
    virtual std::unique_ptr<BaseGeometry> clone() const = 0;

    ~BaseGeometry() override;

    VAO* getVAO() const;
    EBO* getEBO() const;

    GLuint getVAOID() const override;
    GLuint getEBOID() const override;
    GLuint getVBO(VBOType vboType) override;
    size_t getIndicesCount() const override;
    size_t getVerticesCount() override;
    void initVAO() override;
    void initEBO(const std::vector<unsigned int> &indices, GLenum dataType) override;
    void initVBO(const std::vector<float> &data, VBOType vboType, int comp, int location, GLenum dataType) override;
    void bindVBO(VBOType vboType) override;
    void draw() override;

    void setPos(const int location, const std::vector<glm::vec2> &pos) override;
    void setPos(const int location, const std::vector<glm::vec3> &pos) override;
    void setPos(const int location, const std::vector<glm::vec4> &pos) override;
    void setCol(const int location, const std::vector<glm::vec3> &cols) override;
    void setCol(const int location, const std::vector<glm::vec4> &cols) override;
    void setNormal(const int location, const std::vector<glm::vec3> &normals) override;
    void setUV(const int location, const std::vector<glm::vec2> &uvs) override;
    void setIndices(const std::vector<glm::uvec3> &indices) override;

    std::string getTraceId() const override;
protected:
    DrawType m_DrawType                                                 { DrawType::DRAW_ARRAYS   }; // 绘制类型：基于索引还是基于顶点
    GLuint m_DrawMode                                                   { 0 };  // 数据装配类型
    GeometryType m_GeometryType                                         { GeometryType::NONE      };

    VAO* m_VAO                                                          { nullptr };
    EBO* m_EBO                                                          { nullptr };
    std::unordered_map<int, VBOStruct>   m_VboMap;
    size_t m_IndicesCount                                               { 0 };
    size_t m_VerticesCount                                              { 0 };

    OrthoBase m_OrthoBase;

    std::string m_GeoTraceId;  // 通过全局id生成器生成，每个几何对象的id唯一
};

#endif //ENGINE_BASEGEOMETRY_H
